/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package retrofit2;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;

import okhttp3.Request;
import okio.Timeout;

/**
 * 默认的call adapter
 * 这个适配器工厂好像就是根据是否有executor，来确定要不要异步执行的
 */
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    private final @Nullable
    Executor callbackExecutor;

    DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public @Nullable
    CallAdapter<?, ?> get(
            Type returnType, Annotation[] annotations, Retrofit retrofit) {
        // 这个工厂类只处理Call类型的rawType的方法 如果返回类型不是Call 则返回null选用下一个 在Retrofit.nextCallAdapter()
        if (getRawType(returnType) != Call.class) {
            return null;
        }
        // 如果返回类型不是具体的已定义参数，则报错  谁知道你想要什么啊
        if (!(returnType instanceof ParameterizedType)) {
            throw new IllegalArgumentException(
                    "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
        }
        // 获取参数的（如List<String>）第0个具体类型
        final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

        // 获取executor
        final Executor executor =
                Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
                        ? null
                        : callbackExecutor;

        // 实例化一个call adapter返回
        return new CallAdapter<Object, Call<?>>() {

            /**
             * 支持的返回值类型
             * @return
             */
            @Override
            public Type responseType() {
                return responseType;
            }

            /**
             * 返回一个具体的adapt
             * @param call  TODO call 这是啥
             * @return
             */
            @Override
            public Call<Object> adapt(Call<Object> call) {
                // 这里 如果有executor 则new一个异步的Call 否则直接返回call不做什么处理
                return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
            }
        };
    }

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;

        final Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }

        // 异步执行的方法实现
        @Override
        public void enqueue(final Callback<T> callback) {
            Objects.requireNonNull(callback, "callback == null");
            // 给call里面设置一个新的call back
            delegate.enqueue(
                    new Callback<T>() {
                        @Override
                        public void onResponse(Call<T> call, final Response<T> response) {
                            // TODO call会是什么，这里为什么不用到，难道事就这个类？
                            // 通过调用executor的方法，达到异步的目的
                            callbackExecutor.execute(
                                    () -> {
                                        if (delegate.isCanceled()) {
                                            // Emulate（模拟） OkHttp's behavior of throwing/delivering an IOException on
                                            // cancellation.
                                            // 在call被取消了的情况下模拟OkHttp的行为 抛出Io异常
                                            callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                                        } else {
                                            callback.onResponse(ExecutorCallbackCall.this, response);
                                        }
                                    });
                        }

                        @Override
                        public void onFailure(Call<T> call, final Throwable t) {
                            // 同样异步执行
                            callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
                        }
                    });
        }

        @Override
        public boolean isExecuted() {
            return delegate.isExecuted();
        }

        @Override
        public Response<T> execute() throws IOException {
            return delegate.execute();
        }

        @Override
        public void cancel() {
            delegate.cancel();
        }

        @Override
        public boolean isCanceled() {
            return delegate.isCanceled();
        }

        @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
        @Override
        public Call<T> clone() {
            return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
        }

        @Override
        public Request request() {
            return delegate.request();
        }

        @Override
        public Timeout timeout() {
            return delegate.timeout();
        }
    }
}
